﻿using System;
using System.ComponentModel;
using System.Configuration;
using System.IO;
using System.Net;
using System.Reflection;
using System.Windows.Forms;

namespace harbar.net.Utils.APM
{
    public partial class frmMain : Form
    {
        private void frmMain_Load(object sender, EventArgs e)
        {
            this.Text = AssemblyTitle;
            lblApplicationName.Text = AssemblyTitle;
            lblVersion.Text = "v" + AssemblyVersion;
            lblCopyright.Text = AssemblyCopyright;
            lblDescription.Text = AssemblyDescription;

            try
            {
                if (!Helper.IisInstalled())
                {
                    MessageBox.Show(APM.Resource.IISNotPresent);
                    Application.Exit();
                }
                else
                {
                    if (Helper.W3svcStatus() == "Stopped")
                    {
                        MessageBox.Show(Resource.W3SVCStopped);
                    }
                    chkWarmUp.Checked = PerformWarmUp;
                    chkStsAdm.Checked = IncludeStsAdm;
                    txtWarmUrpUrls.Text = WarmUpUrlsDisplay;
                    radBalloon.Checked = BalloonNotifications;
                  
                    CreateAppPoolList();
                    CreateAppPoolMenuItems();
                }    
            }
            catch (Exception ex)
            {
                MessageBox.Show(Resource.ConfigError);
                Helper.WriteEvent(ex);
                Application.Exit();
            }
        }

        
        #region Application Pool Display

        private void CreateAppPoolMenuItems()
        {
            try
            {
                // remove App Pools 
                int count = cmsMain.Items.Count - 6;  // 6 static items
                for (int x = 0; x < count; x++)       // no items on first run
                {
                    cmsMain.Items.Remove(cmsMain.Items[0]);
                }

                // add App Pools
                AppPools aps = Helper.GetAppPools();
                foreach (AppPool ap in aps)
                {
                    // if not hidden
                    if (!clbAppPools.GetItemChecked(clbAppPools.Items.IndexOf(ap.Name)))
                    {
                        ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
                        toolStripMenuItem.Name = ap.Name;
                        toolStripMenuItem.Text = ap.Name;

                        // get Process ID(s)...
                        string pid = "";
                        if (ap.Pids != null)
                        {
                            string[] pids = ap.Pids.Split(',');
                            switch (pids.Length)
                            {
                                case 1:
                                    break;
                                case 2:
                                    pid = " [PID: " + pids[0] + "]";
                                    break;
                                default:
                                    pid = " [PIDs: ";
                                    for (int x = 0; x < pids.Length - 1; x++)
                                    {
                                        pid += pids[x] + ", ";
                                    }
                                    pid = pid.Remove(pid.Length - 2);
                                    pid += "]";
                                    break;
                            }
                        }

                        // get State...
                        if (ap.Status == "Started")
                        {
                            if (pid != "")
                            {
                                toolStripMenuItem.Text = toolStripMenuItem.Text + pid;
                                toolStripMenuItem.ToolTipText = ap.Status;
                            }
                            else
                            {
                                toolStripMenuItem.ToolTipText = ap.Status + " (Not spun up)";
                            }
                        }
                        else
                        {
                            toolStripMenuItem.ToolTipText = ap.Status;
                        }

                        toolStripMenuItem.MouseDown += new MouseEventHandler(ap_Click);
                        cmsMain.Items.Insert(0, toolStripMenuItem);
                    }
                }
            }
            catch (Exception ex)
            {
                Notify(APM.Resource.AppPoolEnum, ToolTipIcon.Error, false);
                Helper.WriteEvent(ex);
            }

        }

        private void CreateAppPoolList()
        {
            try
            {
                clbAppPools.Items.Clear();
                foreach (string ap in Helper.GetAppPoolNames())
                {
                    bool blnChecked = false;
                    for (int x = 0; x < HiddenAppPools.Length; x++)
                    {
                        if (HiddenAppPools[x] == ap)
                        {
                            blnChecked = true;
                        }
                    }
                    clbAppPools.Items.Add(ap, blnChecked);
                }
            }
            catch (Exception ex)
            {
                Notify(APM.Resource.AppPoolEnum, ToolTipIcon.Error, false);
                Helper.WriteEvent(ex);
            }
        }

        #endregion

        #region App Pool Actions

        private void ap_Click(object sender, MouseEventArgs e)
        {
            try
            {
                ToolStripMenuItem tsmu = (ToolStripMenuItem)sender;
                Notify("Reclcying " + tsmu.Name, ToolTipIcon.Info, true);
                Helper.RecycleAppPool(tsmu.Name);
                Notify(tsmu.Name + " recycled!", ToolTipIcon.Info, PerformWarmUp);
                if (PerformWarmUp)
                {
                    WarmUp();
                }
            }
            catch (Exception ex)
            {
                Notify(ex.Message, ToolTipIcon.Error, false);
                Helper.WriteEvent(ex);
            }
        }

        private void refreshAppPoolsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateAppPoolList();
            CreateAppPoolMenuItems();
        }

        #endregion

        #region SharePoint Service Management

        private void restartWSSTimerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Notify("Restarting WSS Timer", ToolTipIcon.Info, true);
            try
            {
                Helper.RestartService("SPTimerV3");
                Notify("WSS Timer restarted!", ToolTipIcon.Info, false);
            }
            catch (Exception ex)
            {
                Notify(ex.Message, ToolTipIcon.Error, false);
                Helper.WriteEvent(ex);
            }
        }

        private void restartWSSAdminToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Notify("Restarting WSS Administration", ToolTipIcon.Info, true);
            try
            {
                Helper.RestartService("SPAdmin");
                Notify("WSS Administration restarted!", ToolTipIcon.Info, false);
            }
            catch (Exception ex)
            {
                Notify(ex.Message, ToolTipIcon.Error, false);
                Helper.WriteEvent(ex);
            }
        }

        #endregion

        #region IIS Reset

        private void IisResetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Notify("IIS Reset in progress.", ToolTipIcon.Info, true);
            bgwIisReset.RunWorkerAsync();
        }

        private void bgwIisReset_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                Helper.IisReset();
                Notify("IIS reset!", ToolTipIcon.Info, PerformWarmUp);
            }
            catch (Exception ex)
            {
                Notify(ex.Message, ToolTipIcon.Error, PerformWarmUp);
                Helper.WriteEvent(ex);
            }
        }

        private void bgwIisReset_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (PerformWarmUp)
            {
                WarmUp();
            }
        }

        #endregion

        #region Warm Up 

        private string UrlBeingWarmedUp;

        private void WarmUp()
        {
            if (IncludeStsAdm)
            {
                bgwStsAdm.RunWorkerAsync();
            }
            for (int x = 0; x < WarmUpUrls.Length; x++)
            {
                while (bgwWarmUp.IsBusy)
                {
                    System.Windows.Forms.Application.DoEvents();
                }
                UrlBeingWarmedUp = WarmUpUrls[x];
                bgwWarmUp.RunWorkerAsync(UrlBeingWarmedUp);
            }
        }

        private void bgwWarmUp_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                string url = e.Argument.ToString();
                Notify(url + " being warmed up...", ToolTipIcon.Info, true);  // TODO: do i really want this?
                Helper.HttpGet(e.Argument.ToString());
                Notify(url + " warmed up!", ToolTipIcon.Info, false);
            }
            catch (Exception ex)
            {
                Notify(ex.Message, ToolTipIcon.Warning, false);
                Helper.WriteEvent(ex);
            }
        }

        private void bgwWarmUp_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            CreateAppPoolMenuItems();
        }

        private void bgwStsAdm_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                Helper.ExecuteStsAdm();
                Notify("STSADM Warmed Up!", ToolTipIcon.Info, true);
            }
            catch (Exception ex)
            {
                Notify(ex.Message, ToolTipIcon.Error, PerformWarmUp);
                Helper.WriteEvent(ex);
            }
        }
        #endregion

        #region Options Screen

        private void btnRefreshAppPools_Click(object sender, EventArgs e)
        {
            CreateAppPoolList();
            CreateAppPoolMenuItems();
        }

        private void chkWarmUp_CheckedChanged(object sender, EventArgs e)
        {
            txtWarmUrpUrls.Enabled = chkWarmUp.Checked;
            chkStsAdm.Enabled = chkWarmUp.Checked;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            SaveSettings();
            CreateAppPoolMenuItems();
            Visible = false;
        }

        private void SaveSettings()
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.AppSettings.Settings["BalloonNotifications"].Value = radBalloon.Checked.ToString();
            config.AppSettings.Settings["EnablePostEventWarmUp"].Value = chkWarmUp.Checked.ToString();
            config.AppSettings.Settings["IncludeSTSADM"].Value = chkStsAdm.Checked.ToString();
            config.AppSettings.Settings["URL"].Value = txtWarmUrpUrls.Text;

            string s = "";
            foreach (object item in clbAppPools.CheckedItems)
            {
                s += item.ToString() + "|";
            }
            config.AppSettings.Settings["HiddenAppPools"].Value = s;

            config.Save(ConfigurationSaveMode.Modified, true);
            ConfigurationManager.RefreshSection("appSettings");
        }

        private void lnkWeb_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.harbar.net/");
        }

        private void lnkCheckForUpdates_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                WebRequest request = WebRequest.Create("http://www.harbar.net/apm/version.htm");
                request.Credentials = CredentialCache.DefaultCredentials;
                request.Method = "GET";
                WebResponse response = request.GetResponse();
                Stream dataStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(dataStream);
                string responseFromServer = reader.ReadToEnd();
                response.Close();
                //Debug.WriteLine(responseFromServer);

                if (responseFromServer != AssemblyVersion.ToString())
                {
                    System.Diagnostics.Process.Start("http://www.harbar.net/articles/apm.aspx");
                }
                else
                {
                    MessageBox.Show("You are using the latest version!", "APM Update Check", MessageBoxButtons.OK);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("There was a problem accessing the web service, please try again later.", "APM Update Check", MessageBoxButtons.OK);
                Helper.WriteEvent(ex);
            }
        }

        #endregion

        #region Notification

        private void Notify(string message, ToolTipIcon tti, bool inProg)
        {
            if (message.Length > 63)
            {
                message = message.Substring(0, 63);
            }
            notifyIcon.Text = message;

            if (inProg)
            {
                notifyIcon.Icon = APM.Resource.InProgressIcon;
            }
            else
            {
                notifyIcon.Icon = APM.Resource.NormalIcon;
            }
            if (radBalloon.Checked)
            {
                notifyIcon.ShowBalloonTip(1, AssemblyTitle, message, tti);
            }
        }

        #endregion



        #region AppSettings Accessors

        private bool BalloonNotifications
        {
            get
            {
                return Convert.ToBoolean(ConfigurationManager.AppSettings["BalloonNotifications"].ToString());
            }
        }

        private bool PerformWarmUp
        {
            get
            {
                return Convert.ToBoolean(ConfigurationManager.AppSettings["EnablePostEventWarmUp"].ToString());
            }
        }

        private bool IncludeStsAdm
        {
            get
            {
                return Convert.ToBoolean(ConfigurationManager.AppSettings["IncludeSTSADM"].ToString());
            }
        }

        private string[] WarmUpUrls
        {
            get
            {
                return ConfigurationManager.AppSettings["URL"].Split(',');
            }
        }

        private string WarmUpUrlsDisplay
        {
            get
            {
        
            return ConfigurationManager.AppSettings["URL"];
            }
        }

        private string[] HiddenAppPools
        {
            get
            {
                return ConfigurationManager.AppSettings["HiddenAppPools"].Split('|');
            }
        }

        #endregion

        #region Assembly Attribute Accessors

        public string AssemblyTitle
        {
            get
            {
                // Get all Title attributes on this assembly
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
                // If there is at least one Title attribute
                if (attributes.Length > 0)
                {
                    // Select the first one
                    AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
                    // If it is not an empty string, return it
                    if (titleAttribute.Title != "")
                        return titleAttribute.Title;
                }
                // If there was no Title attribute, or if the Title attribute was the empty string, return the .exe name
                return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
            }
        }

        public string AssemblyVersion
        {
            get
            {
                return Assembly.GetExecutingAssembly().GetName().Version.ToString();
            }
        }

        public string AssemblyDescription
        {
            get
            {
                // Get all Description attributes on this assembly
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
                // If there aren't any Description attributes, return an empty string
                if (attributes.Length == 0)
                    return "";
                // If there is a Description attribute, return its value
                return ((AssemblyDescriptionAttribute)attributes[0]).Description;
            }
        }

        public string AssemblyProduct
        {
            get
            {
                // Get all Product attributes on this assembly
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
                // If there aren't any Product attributes, return an empty string
                if (attributes.Length == 0)
                    return "";
                // If there is a Product attribute, return its value
                return ((AssemblyProductAttribute)attributes[0]).Product;
            }
        }

        public string AssemblyCopyright
        {
            get
            {
                // Get all Copyright attributes on this assembly
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
                // If there aren't any Copyright attributes, return an empty string
                if (attributes.Length == 0)
                    return "";
                // If there is a Copyright attribute, return its value
                return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
            }
        }

        public string AssemblyCompany
        {
            get
            {
                // Get all Company attributes on this assembly
                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
                // If there aren't any Company attributes, return an empty string
                if (attributes.Length == 0)
                    return "";
                // If there is a Company attribute, return its value
                return ((AssemblyCompanyAttribute)attributes[0]).Company;
            }
        }
        #endregion

        #region Tray App Management

        public frmMain()
        {
            InitializeComponent();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Application.Exit();
        }

        private void showSettings(object sender, MouseEventArgs e)
        {
            showMain(sender, e);
        }

        private void showMain(object sender, EventArgs e)
        {
            if (notifyIcon.ContextMenuStrip != null)
                notifyIcon.ContextMenuStrip.Hide();
            Show();
            WindowState = FormWindowState.Normal;
            Focus();
            Activate();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            Hide();
            e.Cancel = true;
            base.OnClosing(e);
        }

        #endregion


    }
}
